//
//  GGRegularExpression.m
//  qqqqqq
//
//  Created by iOSer on 2017/3/2.
//  Copyright © 2017年 iOSer. All rights reserved.
//

#import "GGRegularExpression.h"
#import "GGMatchResult.h"
static NSString * const GGRouteParamPattern=@":[a-zA-Z0-9-_][^/]+";
static NSString * const GGRouteParamNamePattern=@":[a-zA-Z0-9-_]+";
static NSString * const GGRouteParamMatchPattern=@"([^/]+)";
@interface GGRegularExpression()
@property(nonatomic,strong)NSArray * routerParamNamesArr;
@end
@implementation GGRegularExpression
+(GGRegularExpression *)expressionWithPattern:(NSString *)pattern{
    NSError *error;
    GGRegularExpression *exp = [[GGRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
    if (error) {
        NSLog(@"%@",error);
    }
    return exp;
}

-(instancetype)initWithPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options error:(NSError * _Nullable __autoreleasing *)error{
    //将匹配表达式转换成正则表达式
    NSString *transformedPattern = [GGRegularExpression transfromFromPattern:pattern];
    //用转化后的结果初始化父类
    if (self = [super initWithPattern:transformedPattern options:options error:error]) {
        //同时将需要提取的子串的值的Key保存到数组中
        self.routerParamNamesArr = [[self class] routeParamNamesFromPattern:pattern];
    }
    return self;
    
}
//判断是否匹配
-(GGMatchResult *)matchResultForString:(NSString *)string{
    //处理器已经根据正则初始化 处理字符串
    NSArray *array = [self matchesInString:string options:0 range:NSMakeRange(0, string.length)];
    GGMatchResult *result = [[GGMatchResult alloc] init];
    //如果为空说明无法匹配 返回空处理结果
    if (array.count == 0) {
        return result;
    }
    
    result.match = YES;
    NSMutableDictionary *paramDict = [NSMutableDictionary dictionary];
    
    for (NSTextCheckingResult *paramResult in array) {
        
        for (int i = 1; i<paramResult.numberOfRanges&&i<= self.routerParamNamesArr.count; ++i) {
            //取出初始化的KEY数组的key
            NSString *paramName = self.routerParamNamesArr[i-1];
            //从传入字符串中根据处理结果截取字符串
            NSString *paramValue = [string substringWithRange:[paramResult rangeAtIndex:i]];
            //将key value存入字典
            [paramDict setObject:paramValue forKey:paramName];
        }
    }
    //将处理后的属性字典放入返回结果类
    result.paramProperties = paramDict;
    return result;
}

//将匹配表达式转换成正则表达式
+(NSString *)transfromFromPattern:(NSString *)pattern{
    NSString *transfromedPattern = [NSString stringWithString:pattern];
    //将匹配表达式中的KEY :phone[...]  :name[...]取出
    NSArray *paramPatternStrings = [self paramPatternStringsFromPattern:pattern];
    NSError *err;
    //根据正则创建正则对象 获取 :KEY 格式字符串
    NSRegularExpression *paramNamePatternEx = [NSRegularExpression regularExpressionWithPattern:GGRouteParamNamePattern options:NSRegularExpressionCaseInsensitive error:&err];
    
    for (NSString *paramPatternString in paramPatternStrings) {
        
        NSString *replaceParamPatternString = [paramPatternString copy];
        //取出第一个文本检查结果
        NSTextCheckingResult *foundParamNamePatternResult = [paramNamePatternEx matchesInString:paramPatternString options:NSMatchingReportProgress range:NSMakeRange(0, paramPatternString.length)].firstObject;
        
        if (foundParamNamePatternResult) {
            //如果检查结果存在 从key字符串中截取key
            NSString *paramNamePatternString = [paramPatternString substringWithRange:foundParamNamePatternResult.range];
            //从key字符串中替换key为空字符
            replaceParamPatternString = [replaceParamPatternString stringByReplacingOccurrencesOfString:paramNamePatternString withString:@""];
        }
        //如果key字符串长度为0
        if (replaceParamPatternString.length == 0) {
            //则使用‘从/开始取出所有字符串’的正则
            replaceParamPatternString = GGRouteParamMatchPattern;
        }
        //从原始字符串中替换key字符串为正则表达式字符串
        transfromedPattern = [transfromedPattern stringByReplacingOccurrencesOfString:paramPatternString withString:replaceParamPatternString];
    }
    //如果原始串长度不为空 并且第一个字符不是'/' 将'^'拼在表达式前面 表示匹配开始
    if (transfromedPattern.length && !([transfromedPattern characterAtIndex:0] == '/')) {
        transfromedPattern = [@"^" stringByAppendingString:transfromedPattern];
    }
    //将'$'拼在表达式后面 表示匹配结束
    transfromedPattern = [transfromedPattern stringByAppendingString:@"$"];
    return transfromedPattern;
}

+(NSArray *)routeParamNamesFromPattern:(NSString *)pattern{
    NSRegularExpression *paramNameEx = [NSRegularExpression regularExpressionWithPattern:GGRouteParamNamePattern options:NSRegularExpressionCaseInsensitive error:nil];
    //取出表达式中的key串
    NSArray *routeParamStrings = [self paramPatternStringsFromPattern:pattern];
    NSMutableArray *routeParamNames = [[NSMutableArray alloc] init];
    
    for (NSString *routeParamString in routeParamStrings) {
        NSTextCheckingResult *foundRouteParamNameResult = [[paramNameEx matchesInString:routeParamString options:NSMatchingReportProgress range:NSMakeRange(0, routeParamString.length)] firstObject];
        //把key串中的':'替换为空
        if (foundRouteParamNameResult) {
            NSString *routePatamNameString = [routeParamString substringWithRange:foundRouteParamNameResult.range];
            routePatamNameString = [routePatamNameString stringByReplacingOccurrencesOfString:@":" withString:@""];
            [routeParamNames addObject:routePatamNameString];
        }
    }
    return routeParamNames;
}

+(NSArray<NSString *> *)paramPatternStringsFromPattern:(NSString *)pattern{
    NSError *err;
    //根据正则表达式创建正则对象
    NSRegularExpression *paramPatternEx = [NSRegularExpression regularExpressionWithPattern:GGRouteParamPattern options:NSRegularExpressionCaseInsensitive error:&err];
    //将使用正则对象 将字符串传入获得匹配结果数组
    NSArray *paramPatternResults = [paramPatternEx matchesInString:pattern options:NSMatchingReportProgress range:NSMakeRange(0, pattern.length)];
    NSMutableArray *array = [NSMutableArray array];
    //NSTextCheckingResult forEatch匹配结果
    for (NSTextCheckingResult *paramPattern in paramPatternResults) {
        //从原始字符串中截取对应位置字符串
        NSString *paramPatternString = [pattern substringWithRange:paramPattern.range];
        [array addObject:paramPatternString];
    }
    return array;
}

@end
